package com.sl.biz.modular.workflow.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.sl.biz.modular.workflow.dao.domain.entity.WorkflowDO;
import com.sl.biz.modular.workflow.dao.domain.entity.WorkflowInstanceDO;
import com.sl.biz.modular.workflow.dao.service.WorkflowDaoService;
import com.sl.biz.modular.workflow.dao.service.WorkflowInstanceDaoService;
import com.sl.biz.modular.workflow.domain.dto.WorkflowContentDTO;
import com.sl.biz.modular.workflow.domain.request.WorkflowInstanceNextByNodeCodeRequest;
import com.sl.biz.modular.workflow.domain.request.WorkflowInstanceNextRequest;
import com.sl.biz.modular.workflow.domain.request.WorkflowInstanceStartRequest;
import com.sl.biz.modular.workflow.service.WorkflowContentBizService;
import com.sl.biz.modular.workflow.service.WorkflowInstanceBizService;
import com.sl.core.engine.ProcessConfig;
import com.sl.core.engine.log.store.LoggerStoreFactory;
import com.sl.core.engine.log.store.domain.dto.MainLogDTO;
import com.sl.core.engine.rowset.ProcessDbRowSet;
import com.sl.core.workflow.WorkFlowEngine;
import com.sl.core.workflow.listener.IWorkFlowStatusService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class WorkflowInstanceBizServiceImpl implements WorkflowInstanceBizService, IWorkFlowStatusService {
    private final WorkflowInstanceDaoService workflowInstanceDaoService;

    private final WorkflowContentBizService workflowContentBizService;

    private final WorkflowDaoService workflowDaoService;


    @Override
    public List<WorkflowInstanceDO> list(WorkflowInstanceDO workflowInstanceDO) {
        return workflowInstanceDaoService.queryByCondition(workflowInstanceDO);
    }

    @Override
    public String start(WorkflowInstanceStartRequest startRequest) {
        String workflowId = startRequest.getWorkflowId();
        String param = startRequest.getParam();

        WorkflowDO workflowDO = workflowDaoService.getById(workflowId);
        if (ObjectUtil.isNull(workflowDO)) {
            return null;
        }
        WorkflowContentDTO workflowContentDTO = new WorkflowContentDTO();
        workflowContentDTO.setWorkflowId(workflowDO.getId());
        WorkflowContentDTO workflowContentDO = workflowContentBizService.getByWorkflowId(workflowContentDTO);

        String instance = createInstance(workflowDO, workflowContentDO);

        //开始启动流程
        workflowInstanceDaoService.updateStateById(instance, "1");

        ProcessConfig processConfig = workflowContentDO.getProcessConfig();
        processConfig.setInstanceId(instance);
        //执行流程
        WorkFlowEngine.INSTANCE.start(processConfig, param);

        return instance;
    }

    @Override
    public WorkflowInstanceDO getById(WorkflowInstanceDO workflowInstanceDO) {
        return workflowInstanceDaoService.getById(workflowInstanceDO.getId());
    }

    @Override
    public String nextByNodeCode(WorkflowInstanceNextByNodeCodeRequest nodeCodeRequest) {

        //这里
        WorkflowInstanceDO byId = workflowInstanceDaoService.getById(nodeCodeRequest.getId());
        if (ObjectUtil.isNull(byId)) {
            return null;
        }
        //根据编码先找

        ProcessDbRowSet processDbRowSet = new ProcessDbRowSet(null);
        processDbRowSet.initDataSource("default");


        Map<String, Object> map = processDbRowSet.searchStepDataList(null, null, null, byId.getTid(),
                null, null, nodeCodeRequest.getNodeCode());
        if (ObjectUtil.isNull(map)) {
            return null;
        }
        List list = MapUtil.get(map, "data", List.class);

        return "";
    }

    @Override
    public String next(WorkflowInstanceNextRequest startRequest) {
        String id = startRequest.getId();
        WorkflowInstanceDO workflowInstanceDO = workflowInstanceDaoService.getById(id);

        if (ObjectUtil.isNull(workflowInstanceDO)) {
            return null;
        }
        String tid = workflowInstanceDO.getTid();

        WorkflowContentDTO workflowContentDTO = new WorkflowContentDTO();
        workflowContentDTO.setWorkflowId(workflowInstanceDO.getWorkflowId());
        WorkflowContentDTO workflowContentDO = workflowContentBizService.getByWorkflowId(workflowContentDTO);

        ProcessConfig processConfig = workflowContentDO.getProcessConfig();
        processConfig.setInstanceId(workflowInstanceDO.getId());
        processConfig.setTid(tid);
        processConfig.setCompensateFlag(true);

        //查找日志ID
        MainLogDTO db = LoggerStoreFactory.INSTANCE.getMainByTid(tid, null, "db");
        if (ObjectUtil.isNull(db)) {
            return null;
        }
        processConfig.setCompensateLogId(db.getId().toString());
        //执行流程
        WorkFlowEngine.INSTANCE.next(processConfig, startRequest.getParam());

        return null;
    }


    public String runByCode(String workflowInstanceId, String taskCode, String input) {
        return "";
    }

    public String createInstance(WorkflowDO workflowDO, WorkflowContentDTO workflowContentDO) {

        if (ObjectUtil.isNull(workflowDO)) {
            return null;
        }
        if (ObjectUtil.isNull(workflowContentDO)) {
            return null;
        }
        //新增实例表
        WorkflowInstanceDO workflowInstanceDO = new WorkflowInstanceDO();
        workflowInstanceDO.setWorkflowId(workflowDO.getId());
        workflowInstanceDO.setStatus("0");
        workflowInstanceDO.setStartTime(DateUtil.date());
        workflowInstanceDO.setTid(workflowContentDO.getProcessConfig().getTid());
        workflowInstanceDaoService.save(workflowInstanceDO);
        return workflowInstanceDO.getId();
    }


    @InterceptorIgnore(tenantLine = "true")
    @Override
    public void finish(String instanceId) {
        workflowInstanceDaoService.updateStateById(instanceId, "2");
    }

    @Override
    public void error(String instanceId) {
        workflowInstanceDaoService.updateStateById(instanceId, "3");
    }
}
